home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / comm2 / gfndxxxs.lha / GFindXXXSrc / GFindXXX.c < prev    next >
C/C++ Source or Header  |  1996-04-22  |  15KB  |  645 lines

  1. /***************************************************************************
  2.  * GFindXXX.c
  3.  *
  4.  * GFindXXX, Copyright ©1995 Lee Kindness.
  5.  *
  6.  */
  7.  
  8. /* All our includes are in this file */
  9. #include "gst.c"
  10.  
  11. #include "GFindXXX_rev.h"
  12.  
  13. #define PROGNAME "GFindXXX"
  14.  
  15. /* Libraries used, don't auto open them SAS/C :) */
  16. struct Library *GotchaLibBase = NULL;
  17.  
  18. /* The differnet types of search fields */
  19. enum STypes { ST_NONE   = 0,
  20.               ST_SYSTEM = 1,
  21.               ST_SYSOP  = 2,
  22.               ST_PLACE  = 3,
  23.               ST_PHONE  = 4,
  24.               ST_ADR3D  = 5,
  25.               ST_ADR4D  = 6,
  26.               ST_ADR5D  = 7,
  27.               ST_FLAGS  = 8 };
  28.  
  29. struct stypes 
  30. {
  31.     STRPTR      text;
  32.     enum STypes type;
  33. };
  34.  
  35. /* Matches between the arguments supplied for STYPE and the enumeration */
  36. struct stypes texttype[] =
  37. {
  38.     {"system",    ST_SYSTEM},
  39.     {"sys",       ST_SYSTEM},
  40.     {"node",      ST_SYSTEM},
  41.     {"bbs",       ST_SYSTEM},
  42.     {"sysop",     ST_SYSOP},
  43.     {"owner",     ST_SYSOP},
  44.     {"place",     ST_PLACE},
  45.     {"city",      ST_PLACE},
  46.     {"location",  ST_PLACE},
  47.     {"loc",       ST_PLACE},
  48.     {"phone",     ST_PHONE},
  49.     {"telephone", ST_PHONE},
  50.     {"3d",        ST_ADR3D},
  51.     {"3",         ST_ADR3D},
  52.     {"4d",        ST_ADR4D},
  53.     {"4",         ST_ADR4D},
  54.     {"address",   ST_ADR4D},
  55.     {"addr",      ST_ADR4D},
  56.     {"adr",       ST_ADR4D},
  57.     {"5d",        ST_ADR5D},
  58.     {"5",         ST_ADR5D},
  59.     {"domain",    ST_ADR5D},
  60.     {"flags",     ST_FLAGS},
  61.     {"flag",      ST_FLAGS},
  62.     {NULL,        ST_NONE}
  63. };
  64.  
  65. LONG NLSearch(struct gl_context *nl, STRPTR pat, STRPTR npat, enum STypes stype,
  66.               BOOL full, BOOL points, BOOL cutdash, BOOL verbatim, STRPTR lformat);
  67.  
  68. const char *vtag = VERSTAG;
  69.  
  70.  
  71. /***************************************************************************
  72.  * SPrintf() -- Equiv. to sprintf().
  73.  */
  74.  
  75. void SPrintf(char *buffer, char *format, ...)
  76. {
  77.     RawDoFmt(format, (APTR)(&format+1), (void (*))"\x16\xC0\x4E\x75", buffer);
  78. }
  79.  
  80.  
  81. /***************************************************************************
  82.  * LFormat() -- Print out node details, when LFORMAT is selected.
  83.  */
  84.  
  85. /* Character format indicators for the LFORMAT option */
  86. #define SPEC        '%'
  87. #define S_ADDRESS3D '3'
  88. #define S_ADDRESS4D '4'
  89. #define S_ADDRESS5D '5'
  90. #define S_ADDRESS   'A'
  91. #define S_ALERT     'a'
  92. #define S_BAUD      'B'
  93. #define S_BSPACE    'b'
  94. #define S_STAR      'C'
  95. #define S_COST      'c'
  96. /* #define S_       'D' */
  97. #define S_DOMAIN    'd'
  98. /* #define S_       'E' */
  99. #define S_NET       'e'
  100. #define S_FIRSTNAME 'F'
  101. #define S_FLAGS     'f'
  102. /* #define S_       'G' */
  103. #define S_GATE      'g'
  104. /* #define S_       'H' */
  105. #define S_HUB       'h'
  106. /* #define S_       'I' */
  107. #define S_TIME      'i'
  108. /* #define S_       'J' */
  109. /* #define S_       'j' */
  110. /* #define S_       'K' */
  111. /* #define S_       'k' */
  112. /* #define S_       'L' */
  113. #define S_LOCATION  'l'
  114. #define S_MAILONLY  'M'
  115. #define S_BBSNUM    'm'
  116. #define S_NODE      'N'
  117. #define S_NL        'n'
  118. #define S_BVPHONE   'O'
  119. #define S_VPHONE    'o'
  120. #define S_PHONE     'P'
  121. #define S_POINT     'p'
  122. /* #define S_       'Q' */
  123. #define S_DQUOTE    'q'
  124. #define S_REGION    'R'
  125. #define S_RETURN    'r'
  126. #define S_SYSTEM    'S'
  127. #define S_SYSOP     's'
  128. #define S_TYPE      'T'
  129. #define S_TAB       't'
  130. /* #define S_       'U' */
  131. #define S_ADDRESSA  'u'
  132. /* #define S_       'V' */
  133. #define S_VTAB      'v'
  134. /* #define S_       'W' */
  135. #define S_PASSWORD  'w'
  136. /* #define S_       'X' */
  137. #define S_SYSOPE    'x'
  138. /* #define S_       'Y' */
  139. /* #define S_       'y' */
  140. /* #define S_       'Z' */
  141. #define S_ZONE      'z'
  142.  
  143. #define FT_SHORT "%u %S, %l, %s, %P"
  144. #define FT_FULL  "Node %A, \"%S\" is in %l\n"    \
  145.                  "System is listed as %T\n"        \
  146.                  "Operated by %s\n"                        \
  147.                  "Region %R, Hub %h\n"                \
  148.                  "Phone %P, Cost %c\n"                \
  149.                  "Flags %f\n"                                    \
  150.                  "Password %w\n"
  151.  
  152. #define STATE_NONE 0
  153. #define STATE_SPEC 1
  154.  
  155. void LFormat(struct gl_nodeinfo *nd, STRPTR format, BOOL verbatim)
  156. {
  157.     STRPTR s, s2;
  158.     LONG state = STATE_NONE;
  159.     BPTR fh = Output();
  160.     
  161.     for( s = format; *s != '\000'; ++s )
  162.     {
  163.         switch( state )
  164.         {
  165.             case STATE_NONE:
  166.                 if( *s == SPEC )
  167.                     state = STATE_SPEC;
  168.                 else
  169.                     FPutC(fh, *s);
  170.                 break;
  171.             case STATE_SPEC:
  172.                 switch( *s )
  173.                 {
  174.                     case SPEC:
  175.                         FPutC(fh, SPEC);
  176.                         break;
  177.                     case S_NL:
  178.                         FPutC(fh, '\n');
  179.                         break;
  180.                     case S_TAB:
  181.                         FPutC(fh, '\t');
  182.                         break;
  183.                     case S_RETURN:
  184.                         FPutC(fh, '\r');
  185.                         break;
  186.                     case S_VTAB:
  187.                         FPutC(fh, '\v');
  188.                         break;
  189.                     case S_DQUOTE:
  190.                         FPutC(fh, '\"');
  191.                         break;
  192.                     case S_ALERT:
  193.                         FPutC(fh, '\a');
  194.                         break;
  195.                     case S_BSPACE:
  196.                         FPutC(fh, '\b');
  197.                         break;
  198.                     case S_STAR:
  199.                         FPutC(fh, '*');
  200.                         break;
  201.                     case S_SYSTEM:
  202.                         FPuts(fh, nd->name);
  203.                         break;
  204.                     case S_ADDRESS3D:
  205.                         FPrintf(fh, "%ld:%ld/%ld", nd->zone, nd->net,
  206.                                nd->node);
  207.                         break;
  208.                     case S_ADDRESS4D:
  209.                         FPrintf(fh, "%ld:%ld/%ld.%ld", nd->zone, nd->net,
  210.                                nd->node, nd->point);
  211.                         break;
  212.                     case S_ADDRESS5D:
  213.                     case S_ADDRESS:
  214.                         FPrintf(fh, "%ld:%ld/%ld.%ld@%s", nd->zone, nd->net,
  215.                                nd->node, nd->point, nd->domain);
  216.                         break;
  217.                     case S_ADDRESSA:
  218.                         if( nd->point )
  219.                             FPrintf(fh, "%ld:%ld/%ld.%ld", nd->zone, nd->net,
  220.                                nd->node, nd->point);
  221.                         else
  222.                             FPrintf(fh, "%ld:%ld/%ld", nd->zone, nd->net,
  223.                                nd->node);
  224.                         break;
  225.                     case S_LOCATION:
  226.                         FPuts(fh, nd->location);
  227.                         break;
  228.                     case S_SYSOP:
  229.                         FPuts(fh, nd->sysop);
  230.                         break;
  231.                     case S_FIRSTNAME:
  232.                         for( s2 = nd->sysop;
  233.                              (*s2) && (*s2 != ' ');
  234.                              ++s2 )
  235.                             FPutC(fh, *s2);
  236.                         break;
  237.                     case S_SYSOPE:
  238.                     case S_GATE:
  239.                         for( s2 = nd->sysop; *s2 != '\0'; ++s2 )
  240.                             if( *s2 == ' ' )
  241.                                 FPutC(fh, '.');
  242.                             else
  243.                                 FPutC(fh, tolower(*s2));
  244.                         if( *s == S_SYSOPE )
  245.                             break;
  246.                         if( nd->point )
  247.                             FPrintf(fh, "@p%ld.f%ld.n%ld.z%ld", nd->point, nd->node,
  248.                                nd->net, nd->zone);
  249.                         else
  250.                             FPrintf(fh, "@f%ld.n%ld.z%ld", nd->node,
  251.                                nd->net, nd->zone);
  252.                         break;
  253.                     case S_TYPE:
  254.                         /* Gotchlib does not support this... implement by hand */
  255.                         if( nd->point )
  256.                             FPuts(fh, "Point");
  257.                         else if( (nd->zone == nd->net) && (nd->node == 0) )
  258.                             FPuts(fh, "Zone");
  259.                         else if( (nd->region == nd->net) && (nd->node == 0) )
  260.                             FPuts(fh, "Region");
  261.                         else if( nd->node == 0 )
  262.                             FPuts(fh, "Host");
  263.                         else if( nd->hub == nd->node )
  264.                             FPuts(fh, "Hub");
  265.                         else
  266.                             FPuts(fh, "Node");
  267.                         break;
  268.                     case S_BBSNUM:
  269.                         if( strstr(nd->flags, "MO") )
  270.                         {
  271.                             FPuts(fh, "MAIL ONLY");
  272.                             break;
  273.                         }
  274.                         /* FALLTHRU!!! */
  275.                     case S_PHONE:
  276.                         if( verbatim )
  277.                             FPuts(fh, nd->phone);
  278.                         else
  279.                             FPuts(fh, nd->tphone);
  280.                         break;
  281.                     case S_MAILONLY:
  282.                         if( strstr(nd->flags, "MO") )
  283.                             FPuts(fh, "MAIL ONLY");
  284.                         break;
  285.                     case S_BVPHONE:
  286.                         if( strstr(nd->flags, "MO") )
  287.                         {
  288.                             FPuts(fh, "MAIL ONLY");
  289.                             break;
  290.                         }
  291.                         /* FALLTHRU!!! */
  292.                     case S_VPHONE:
  293.                         FPuts(fh, nd->phone);
  294.                         break;
  295.                     case S_BAUD:
  296.                         FPuts(fh, nd->baud);
  297.                         break;
  298.                     case S_COST:
  299.                         if(nd->cost != -1)
  300.                             FPrintf(fh, "%01ld.%02ld", nd->cost/100, nd->cost%100);
  301.                         else
  302.                             FPrintf(fh, "undialable");
  303.                         break;
  304.                     case S_FLAGS:
  305.                         FPuts(fh, nd->flags);
  306.                         break;
  307.                     case S_TIME:
  308.                         if( strstr(nd->flags, "CM") )
  309.                             FPuts(fh, "24hr");
  310.                         else
  311.                             if( s2 = strstr(nd->flags, "U,") )
  312.                                 if( s2 = strstr(s2, ",T") )
  313.                                 {
  314.                                     LONG on_min   = 0;
  315.                                     LONG off_min  = 0;
  316.                                     LONG on_hour  = (LONG)(s2[2] - 'A');
  317.                                     LONG off_hour = (LONG)(s2[3] - 'A');
  318.                                     if( on_hour > 23 )
  319.                                     {
  320.                                         on_hour -= (LONG)('a' - 'A');
  321.                                         on_min = 30;
  322.                                     }
  323.                                     if( off_hour > 23 )
  324.                                     {
  325.                                         off_hour -= (LONG)('a' - 'A');
  326.                                         off_min = 30;
  327.                                     }
  328.                                     FPrintf(fh,"%02ld:%02ld->%02ld:%02ld (UTC)", on_hour, on_min, off_hour, off_min);
  329.                                 } else
  330.                                     FPuts(fh, "ZMH only");
  331.                             else
  332.                                 FPuts(fh, "ZMH only");
  333.                         break;
  334.                     case S_PASSWORD:
  335.                         FPuts(fh, (STRPTR)nd->password[0] ? (STRPTR)nd->password : (STRPTR)"none");
  336.                         break;
  337.                     case S_ZONE:
  338.                         FPrintf(fh, "%ld", nd->zone);
  339.                         break;
  340.                     case S_NET:
  341.                         FPrintf(fh, "%ld", nd->net);
  342.                         break;
  343.                     case S_NODE:
  344.                         FPrintf(fh, "%ld", nd->node);
  345.                         break;
  346.                     case S_POINT:
  347.                         FPrintf(fh, "%ld", nd->point);
  348.                         break;
  349.                     case S_DOMAIN: /*DING*/
  350.                         FPuts(fh, nd->domain);
  351.                         break;
  352.                     case S_REGION:
  353.                         FPrintf(fh, "%ld", nd->region);
  354.                         break;
  355.                     case S_HUB:
  356.                         FPrintf(fh, "%ld", nd->hub);
  357.                         break;
  358.                 }
  359.                 state = STATE_NONE;
  360.                 break;
  361.         }    
  362.     }
  363.     FPutC(fh, '\n');
  364. }
  365.  
  366. /***************************************************************************
  367.  * PrintNode() -- Print out node details.
  368.  */
  369.  
  370. void PrintNode(struct gl_nodeinfo *nd, BOOL full, BOOL verbatim, STRPTR lformat)
  371. {
  372.     if( lformat )
  373.         LFormat(nd, lformat, verbatim);
  374.     else if( full )
  375.         LFormat(nd, FT_FULL, verbatim);
  376.     else
  377.         LFormat(nd, FT_SHORT, verbatim);
  378. }
  379.  
  380.  
  381. /***************************************************************************
  382.  * NLSearch() -- Called for each search...
  383.  */
  384.  
  385. LONG NLSearch(struct gl_context *nl, STRPTR pat, STRPTR npat, enum STypes stype,
  386.               BOOL full, BOOL points, BOOL cutdash, BOOL verbatim, STRPTR lformat)
  387. {
  388.     LONG ret = 0;
  389.     struct gl_address *ad;
  390.     struct gl_nodeinfo *nd = NULL;
  391.     struct gl_pattern *pt = NULL;
  392.     
  393.     if( (ad = AllocVec(sizeof(struct gl_address), MEMF_CLEAR)) &&
  394.         (nd = AllocVec(sizeof(struct gl_nodeinfo), MEMF_CLEAR)) &&
  395.         (pt = AllocVec(sizeof(struct gl_pattern), MEMF_CLEAR)) )
  396.     {
  397.         STRPTR s = NULL;
  398.         ULONG sig = 0;
  399.         #define ADRBUFF_LEN 100
  400.         char adrbuff[ADRBUFF_LEN];
  401.         
  402.         /* convert */
  403.         GL_XtractInfos(ad, npat);
  404.         
  405.         switch( stype )
  406.         {
  407.             case ST_SYSTEM:
  408.                 s = nd->name;
  409.                 break;
  410.             
  411.             case ST_SYSOP:
  412.                 s = nd->sysop;
  413.                 break;
  414.             
  415.             case ST_PLACE:
  416.                 s = nd->location;
  417.                 break;
  418.             
  419.             case ST_PHONE:
  420.                 if( !cutdash )
  421.                 {
  422.                     if( verbatim )
  423.                         s = nd->phone;
  424.                     else
  425.                         s = nd->tphone;
  426.                 } else
  427.                     s = (STRPTR)-1;
  428.                 break;
  429.             
  430.             case ST_ADR3D:
  431.             case ST_ADR4D:
  432.             case ST_ADR5D:
  433.                 s = (STRPTR)-2;
  434.                 break;                
  435.             
  436.             case ST_FLAGS:
  437.                 s = nd->flags;
  438.                 break;
  439.         }
  440.     
  441.         if( s && GL_FindNodeFirst(ad, nl, nd, pt) )
  442.             do
  443.             {
  444.                 if( !(points && ad->point) )
  445.                 {
  446.                     STRPTR ss;
  447.                     
  448.                     if( s == (STRPTR)-1 )
  449.                     {
  450.                         STRPTR src;
  451.                         
  452.                         if( verbatim )
  453.                             src = nd->phone;
  454.                         else
  455.                             src = nd->tphone;
  456.                         
  457.                         /* Strip out dashes */
  458.                         if( ss = AllocVec(strlen(src)+1, MEMF_CLEAR) )
  459.                         {
  460.                             STRPTR s2, s3;
  461.                             s3 = ss;
  462.                             for( s2 = src ; *s2 != '\0'; s2++ )
  463.                             {
  464.                                 if( *s2 != '-' )
  465.                                 {
  466.                                     *s3 = *s2;
  467.                                     s3++;
  468.                                 }
  469.                             }    
  470.                         }
  471.                     } else if( s == (STRPTR)-2 )
  472.                     {
  473.                         ss = adrbuff;
  474.                         switch( stype )
  475.                         {
  476.                             case ST_ADR3D:
  477.                                 SPrintf(ss, "%ld:%ld/%ld", nd->zone, nd->net, nd->node);
  478.                                 break;
  479.                             case ST_ADR4D:
  480.                                 SPrintf(ss, "%ld:%ld/%ld.%ld", nd->zone, nd->net, nd->node, nd->point);
  481.                                 break;
  482.                             case ST_ADR5D:
  483.                                 SPrintf(ss, "%ld:%ld/%ld.%ld@%s", nd->zone, nd->net, nd->node, nd->point, nd->domain);
  484.                                 break;
  485.                             default:
  486.                                 ss = NULL;
  487.                         }
  488.                     } else
  489.                         ss = s;
  490.                     
  491.                     if( ss )
  492.                     {
  493.                         if( MatchPatternNoCase(pat, ss) )
  494.                         {
  495.                             ++ret;
  496.                             PrintNode(nd, full, verbatim, lformat);
  497.                         }
  498.                     }
  499.                     
  500.                     if( s == (STRPTR)-1 )
  501.                         FreeVec(ss);
  502.                 }
  503.             } while( (GL_FindNodeNext(ad, nl, nd, pt)) && (!(sig = CheckSignal(SIGBREAKF_CTRL_C))) );
  504.             if( sig )
  505.                 PrintFault(ERROR_BREAK, "# " PROGNAME);
  506.     }
  507.     if( pt )
  508.         FreeVec(pt);
  509.     if( nd )
  510.         FreeVec(nd);
  511.     if( ad )
  512.         FreeVec(ad);
  513.     
  514.     return ret;
  515. }
  516.  
  517.  
  518. /***************************************************************************
  519.  * main() --
  520.  */
  521. int main(int argc, char **argv)
  522. {
  523.     int ret = RETURN_FAIL;
  524.     
  525.     /* Open libraries */
  526.     if( (GotchaLibBase = OpenLibrary("gotcha.library", 1)) &&
  527.         (DOSBase->dl_lib.lib_Version >= 36) ) 
  528.     {
  529.         /* Parse arguments */
  530.         struct RDArgs *rda;
  531.         #define DEF_NODELIST "Nodelist:"
  532.         #define DEF_NPAT "*"
  533.         #define DEF_STYPE "system"
  534.         #define TEMPLATE "PATTERN/M/A,N=NPAT/K,S=STYPE/K,FULL/S,POINTS/S,VERBATIM/S,STRIPDASHES/S,QUIET=NOINFO/S,LFORMAT/K,NODELIST/K"
  535.         #define OPT_PATTERN 0
  536.         #define OPT_NPAT 1
  537.         #define OPT_STYPE 2
  538.         #define OPT_FULL 3
  539.         #define OPT_POINTS 4
  540.         #define OPT_VERBATIM 5
  541.         #define OPT_STRIPDASHES 6
  542.         #define OPT_NOINFO 7
  543.         #define OPT_LFORMAT 8
  544.         #define OPT_NODELIST 9
  545.         #define OPT_MAX 10
  546.         STRPTR args[OPT_MAX] = {0, DEF_NPAT, DEF_STYPE, 0, 0, 0, 0, 0, 0, DEF_NODELIST};
  547.  
  548.         if( rda = ReadArgs(TEMPLATE, (LONG *)&args, NULL) ) 
  549.         {
  550.             STRPTR s;
  551.             
  552.             struct gl_context *nl;
  553.  
  554.             /* Open nodelist */
  555.             if( nl = GL_OpenNL(args[OPT_NODELIST]) )
  556.             {
  557.                 STRPTR *pata;
  558.                 LONG n = 0;
  559.                 LONG matches = 0;
  560.                 enum STypes st = ST_NONE;
  561.                 struct stypes *mat;
  562.                 
  563.                 for( mat = texttype;
  564.                      (mat->text) && (st == ST_NONE);
  565.                      mat++ )
  566.                 {
  567.                     if( stricmp(args[OPT_STYPE], mat->text) == 0 )
  568.                         st = mat->type;
  569.                 }
  570.                 if( st == ST_NONE )
  571.                     st = ST_SYSTEM;
  572.                 
  573.                 pata = (void *) args[OPT_PATTERN];
  574.                 
  575.                 ret = RETURN_OK;
  576.                 
  577.                 while( (s = pata[n]) && !ret ) 
  578.                 {
  579.                     STRPTR pattern;
  580.                     /* Act on the pattern */
  581.                 
  582.                     /* Alloc buffer for tokenized widcard */
  583.                     if( pattern = AllocVec(strlen(s)*3, MEMF_CLEAR) )
  584.                     {
  585.                         /* Parse wildcard */
  586.                         if( ParsePatternNoCase(s, pattern, strlen(s)*3) != -1 )
  587.                         {
  588.                         
  589.                             LONG num;
  590.                             
  591.                             /* CallFunc! */
  592.                             
  593.                             if( (num = NLSearch(nl,
  594.                                                 pattern,
  595.                                                 args[OPT_NPAT],
  596.                                                 st,
  597.                                   (BOOL)args[OPT_FULL],
  598.                                   (BOOL)args[OPT_POINTS],
  599.                                   (BOOL)args[OPT_STRIPDASHES],
  600.                                   (BOOL)args[OPT_VERBATIM],
  601.                                   args[OPT_LFORMAT])) == -1 )
  602.                             {
  603.                                 if( !args[OPT_NOINFO] )
  604.                                     PrintFault(IoErr(), "# " PROGNAME);
  605.                                 ret = RETURN_FAIL;
  606.                             } else if( num == 0 )
  607.                             {
  608.                                 if( !args[OPT_NOINFO] )
  609.                                     Printf("# No matches for \"%s\"\n", s);
  610.                             }
  611.                             else
  612.                                 matches += num;
  613.  
  614.                         }
  615.                         FreeVec(pattern);
  616.                     }
  617.                     n++;
  618.                 }
  619.                 
  620.                 if( matches )
  621.                 {
  622.                     if( !args[OPT_NOINFO] )
  623.                         Printf("# %ld %s found.\n",
  624.                                matches,
  625.                                ((matches == 1) ? "match" : "matches"));
  626.                 }
  627.                 else
  628.                 {
  629.                     if( !args[OPT_NOINFO] )
  630.                         Printf("# No matches\n");
  631.                 }
  632.                 
  633.                 if( !args[OPT_NOINFO] )
  634.                     Printf("# " VERS " (" DATE ")\n"
  635.                            "# Copyright (c)Lee Kindness, 2:259/15.46\n");
  636.                 GL_CloseNL(nl);
  637.             }
  638.             FreeArgs(rda);
  639.         } else
  640.             PrintFault(IoErr(), "# " PROGNAME);
  641.         CloseLibrary(GotchaLibBase);
  642.     }
  643.     return ret;
  644. }
  645.